package com.cloudkinto.service.fbaproduct.impl;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.DicBusinessConstant;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.ExcelUtils;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.service.fbaproduct.CustomizedColumnVO;
import com.cloudkinto.service.fbaproduct.FbaProductService;
import com.cloudkinto.service.fbaproduct.ImportExcelUtil;
import com.cloudkinto.service.fbaproduct.vo.*;
import com.cloudkinto.service.file.FileService;
import com.cloudkinto.service.operate.OperateRecordService;
import com.cloudkinto.service.operate.vo.OperateRes;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author zhangyy
 * @date 2020/8/20 9:04
 * @description:
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class FbaProductServiceImpl extends ServiceImpl<ProductInfoDao, ProductInfoDo> implements FbaProductService {
    @Autowired
    private ProductInfoDao dao;
    @Autowired
    private DicBusinessItemDao dicBusinessItemDao;
    @Autowired
    private ProductSkuMapDao productSkuMapDao;
    @Autowired
    private CompanyDao companyDao;
    @Autowired
    private FileService fileService;
    @Autowired
    private FileDao fileDao;
    @Autowired
    private OperateRecordDao operateRecordDao;
    @Autowired
    private OperateRecordService operateRecordService;
    @Autowired
    private UserDao userDao;
    @Autowired
    private ImportExcelUtil importExcelUtil;

    @Override
    public SingleResult addInit() {
        List<Map> productTypeList = new ArrayList<>();
        LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.productType);
        List<DicBusinessItemDo> businessItemDoList = dicBusinessItemDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(businessItemDoList)) {
            for (DicBusinessItemDo businessItemDo : businessItemDoList) {
                Map map = new HashMap();
                map.put("id", businessItemDo.getId());
                map.put("value", businessItemDo.getDicItemValue());
                productTypeList.add(map);
            }
        }
        return SingleResult.success(productTypeList);
    }

    @Override
    public FbaProductAddReq add(FbaProductAddReq req, Long userId, Long companyId) {
        addCheck(req, companyId);
        if (companyId == null) {
            throw new BizException(SysConstant.Error_Company);
        }

        ProductInfoDo productInfoDo = new ProductInfoDo();
        BeanUtils.copyProperties(req, productInfoDo);
        productInfoDo.setCompanyId(companyId);
        productInfoDo.setCreateBy(userId);
        productInfoDo.setCreateTime(new Date());
        productInfoDo.setType(2);
        productInfoDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
//        productInfoDo.setProductType(req.getProductType());

//        fileService.uploadFile(req.getProductPictureFileId());

        dao.insert(productInfoDo);
        operateRecordService.operateAddRecord(SysConstant.OPERATE_CREATE_PRODUCT,productInfoDo.getId(),userId,1);
//        addOperateRecord(productInfoDo, userId);

        CompanyDo companyDo = companyDao.selectById(companyId);
        if (companyDo == null) {
            throw new BizException(SysConstant.Company_NotExist);
        }
        String size = null;
        try {
            size = getSize(req.getHeight(), req.getLength(), req.getWidth());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException(SysConstant.Product_Size_Error, req.getCommoditySku());
        }
        String storageSku = req.getCommoditySku();
        if (companyId != 1 && companyId != 44 && companyId != 32)
            storageSku = size + companyDo.getCompanyCode() + productInfoDo.getId();
        productInfoDo.setStorageSku(storageSku);
        dao.updateById(productInfoDo);
        return null;
    }
//
//    private void addOperateRecord(ProductInfoDo entityDo, Long userId) {
//        OperateRecordDo operateRecordDo = new OperateRecordDo();
//        operateRecordDo.setContent("创建了一个商品");
//        operateRecordDo.setOperateBy(userId);
//        operateRecordDo.setType(1);
//        operateRecordDo.setThirdId(entityDo.getId());
//        operateRecordDo.setDeleteFlag(0);
//        operateRecordDo.setOperateTime(new Date());
//        operateRecordDao.insert(operateRecordDo);
//    }

    private void operateRecord(FbaProductUpdateReq req, ProductInfoDo entityDo, Long userId) {
        OperateRecordDo operateRecordDo = new OperateRecordDo();
        operateRecordDo.setThirdId(entityDo.getId());
        operateRecordDo.setDeleteFlag(0);
        operateRecordDo.setOperateTime(new Date());
        operateRecordDo.setType(1);
        operateRecordDo.setRemarks(JSON.toJSONString(entityDo));
        operateRecordDo.setOperateBy(userId);
        StringBuilder stringBuilder = new StringBuilder("");
        float v = req.getHeight() * req.getLength() * req.getWidth();
        float v1 = entityDo.getLength() * entityDo.getWidth() * entityDo.getHeight();
        if (v != v1) {
            stringBuilder.append(SysConstant.OPERATE_UPDATE_PRODUCT_SIZE);
        }
        if (req.getWeight() != entityDo.getWeight()) {
            stringBuilder.append(SysConstant.OPERATE_UPDATE_PRODUCT_WEIGHT);
        }
        operateRecordDo.setContent(stringBuilder.toString());

        operateRecordService.operateAddRecord(stringBuilder.toString(),entityDo.getId(),userId,1);
    }

    //新增校验
    private void addCheck(FbaProductAddReq req, Long companyId) {
        LambdaQueryWrapper<ProductInfoDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductInfoDo::getCommoditySku, req.getCommoditySku()).eq(ProductInfoDo::getCompanyId, companyId).eq(ProductInfoDo::getType, 2);
        int count = this.baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BizException(SysConstant.Order_Product_Repeat, req.getCommoditySku());
        }

    }

    private String getSize(Float width, Float height, Float length) {
        int isize = 0;
        float size = width + height + length;
        int[] sizes = new int[]{60, 100, 160, 200, 260};
        for (int i :
                sizes) {
            if ((int) size < i) {
                isize = i;
                break;
            }
        }
        if (isize < 100) {
            return ("0" + isize).substring(0, 2);
        } else {
            return (isize + "").substring(0, 2);
        }
    }

    @Override
    public SingleResult updateInit(Long id) {
        List<Map> productTypeList = (List<Map>) addInit().getData();
        Map result = new HashMap();
        result.put("productTypeList", productTypeList);

        ProductInfoDo productInfoDo = dao.selectById(id);
        FbaProductDetailRes res = new FbaProductDetailRes();
        BeanUtils.copyProperties(productInfoDo, res);
        res.setProductPictureFileUrl(fileService.getFilePath(productInfoDo.getProductPictureFileId()));
//        DicBusinessItemDo businessItemDo = dicBusinessItemDao.selectById(productInfoDo.getProductType());
//        if(businessItemDo!=null){
//            res.setProductTypeName(businessItemDo.getDicItemValue());
//        }

        result.put("detail", res);

        return SingleResult.success(result);
    }

    @Override
    public FbaProductUpdateReq update(FbaProductUpdateReq updateVo, Long userId, Long companyId) {
        ProductInfoDo productInfoDo = dao.selectById(updateVo.getId());
//        if (updateVo.getProductPictureFileId() != null) {
//            fileService.deleteFile(productInfoDo.getProductPictureFileId());
//            fileService.uploadFile2(updateVo.getProductPictureFileId(),productInfoDo.getProductPictureFileId());
//        }
        BeanUtils.copyProperties(updateVo, productInfoDo);
        productInfoDo.setUpdateBy(userId);
        productInfoDo.setUpdateTime(new Date());

        dao.updateById(productInfoDo);

        operateRecord(updateVo, productInfoDo, userId);
        return null;
    }

    @Override
    public int delete(Long id, Long userId) {
        ProductInfoDo productInfoDo = dao.selectById(id);
        productInfoDo.setDeleteBy(userId);
        productInfoDo.setDeleteTime(new Date());
        dao.updateById(productInfoDo);

        dao.deleteById(id);
        fileService.deleteFile(productInfoDo.getProductPictureFileId());
        return 0;
    }

    @Override
    public void deleteBatch(List<Long> ids, Long userId) {
        dao.deleteBatchIds(ids);
    }

    @Override
    public FbaProductDetailRes detail(Long id) {
        ProductInfoDo productInfoDo = dao.selectById(id);
        FbaProductDetailRes res = new FbaProductDetailRes();
        BeanUtils.copyProperties(productInfoDo, res);
        res.setProductPictureFileUrl(fileService.getFilePath(productInfoDo.getProductPictureFileId()));
//        DicBusinessItemDo businessItemDo = dicBusinessItemDao.selectById(productInfoDo.getProductType());
//        if(businessItemDo!=null){
//            res.setProductTypeName(businessItemDo.getDicItemValue());
//        }

        //操作日志
        List<OperateRes> operateResList = operateRecordService.getOperateList(id, 1);
        res.setOperateResList(operateResList);
        return res;
    }

    @Override
    public SingleResult pageInit() {
        List<Map> productTypeList = new ArrayList<>();
        LambdaQueryWrapper<DicBusinessItemDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DicBusinessItemDo::getDicBusinessId, DicBusinessConstant.productType);
        List<DicBusinessItemDo> businessItemDoList = dicBusinessItemDao.selectList(wrapper);
        if (!CollectionUtils.isEmpty(businessItemDoList)) {
            for (DicBusinessItemDo businessItemDo : businessItemDoList) {
                Map map = new HashMap();
                map.put("id", businessItemDo.getId());
                map.put("value", businessItemDo.getDicItemValue());
                productTypeList.add(map);
            }
        }
        return SingleResult.success(productTypeList);
    }

    @Override
    public SingleResult productType() {
        return null;
    }

    @Override
    public PageResult getListPage(Map<String, String> map) {
        QueryWrapper<ProductInfoDo> wrapper = queryBuild(map);
        IPage<ProductInfoDo> page = pageInit(map);
        page = this.page(page, wrapper);
        List<FbaProductListPage> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    private IPage<ProductInfoDo> pageInit(Map<String, String> map) {
        IPage<ProductInfoDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    //查询分页列表之后对列表数据的处理
    private List<FbaProductListPage> handlerListAfter(List<ProductInfoDo> list) {
        List<FbaProductListPage> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            for (ProductInfoDo infoDo : list) {
                FbaProductListPage res = new FbaProductListPage();
                BeanUtils.copyProperties(infoDo, res);
                res.setProductPictureFileUrl(fileService.getFilePath(infoDo.getProductPictureFileId()));
//                DicBusinessItemDo businessItemDo = dicBusinessItemDao.selectById(infoDo.getProductType());
//                if (businessItemDo != null) {
//                    res.setProductType(businessItemDo.getDicItemValue());
//                }
                CompanyDo companyDo = companyDao.selectById(infoDo.getCompanyId());
                if (companyDo != null) {
                    res.setCompanyCode(companyDo.getCompanyCode());
                }
                result.add(res);
            }
        }
        return result;
    }

    private QueryWrapper<ProductInfoDo> queryBuild(Map<String, String> map) {
        QueryWrapper<ProductInfoDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.and(i -> i.like("commodity_sku", map.get("keyword"))
                    .or().like("storage_sku", map.get("keyword"))
                    .or().like("commodity_name", map.get("keyword"))
                    .or().like("product_name", map.get("keyword")))
                    .or().like("brand_model", map.get("keyword"));
        }
        if (StringUtils.isNotBlank(map.get("productType"))) {
            wrapper.like("product_type", map.get("productType"));
        }
        if (StringUtils.isNotBlank(map.get("companyId"))) {
            wrapper.eq("company_id", map.get("companyId"));
        }
        wrapper.eq("type", 2);
        return wrapper.orderByDesc("id");
    }

    @Override
    public SingleResult importProductFile(MultipartFile file, Long userId, Long companyId, List<CustomizedColumnVO> customizedColumn) throws Exception {
        if (StringUtils.isEmpty(file.getName())) {
            throw new BizException(SysConstant.File_Name_Null);
        }
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!GlobalConstants.IMG_TYPE_XLS.equals(suffix.toUpperCase()) &&
                !GlobalConstants.IMG_TYPE_XLSX.equals(suffix.toUpperCase())) {
            throw new BizException(SysConstant.File_Form_Incorrect);
        }
        List<Object> list = new ArrayList<>();
        try {
            list = importExcelUtil.parseExcel(file.getInputStream(), file.getOriginalFilename(), customizedColumn);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (list.size() == 0) {
            throw new BizException(SysConstant.No_Data);
        }
        Boolean flag = false;
        Boolean flag1 = false;
        Long companyID = null;
        for (Object excelData : list) {
            FbaProductAddReq addReq = new FbaProductAddReq();
            Field[] fields = excelData.getClass().getFields();
            Field[] declaredFields = addReq.getClass().getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                for (int j = 0; j < declaredFields.length; j++) {
                    String name = fields[i].getName();
//                    if("productPictureFileId".equals(name)){
//                        flag=true;
//                    }
                    if ("companyCode".equals(name)) {
                        flag1 = true;
                    }
                    if (name.equals(declaredFields[j].getName())) {
                        declaredFields[j].setAccessible(true);
                        Object o = fields[i].get(excelData);
                        String typeName = declaredFields[j].getType().getTypeName();
                        if (null != o && o != "") {
                            String s = o.toString();
                            if (typeName.equals("float") && isNumber(s)) {
                                declaredFields[j].set(addReq, Float.parseFloat(s));
                            } else if (typeName.equals("double") && isNumber(s)) {
                                declaredFields[j].set(addReq, Double.parseDouble(s));
                            } else if (typeName.equals("java.lang.Long") && isNumber(s)) {
                                declaredFields[j].set(addReq, Long.parseLong(s.split("\\.")[0]));
                            } else if (typeName.equals("java.lang.String")) {
                                declaredFields[j].set(addReq, o);
                            }
                        }
                        break;
                    }
                }
            }
//            if(flag && StringUtils.isNotEmpty(excelData.getClass().getDeclaredField("productPictureFileId").get(excelData).toString())){
//                long productPictureFileId = Long.parseLong(excelData.getClass().getDeclaredField("productPictureFileId").get(excelData).toString().split("\\.")[0]);
//                String url = fileService.getFilePath(productPictureFileId);
//                if(StringUtils.isNotEmpty(url)){
//                    Long fileId = fileService.uploadExcelImage(url, userId);
//                    addReq.setProductPictureFileId(productPictureFileId);
//                }
//                flag=false;
//            }
            if (flag1) {
                Object companyCode = excelData.getClass().getField("companyCode").get(excelData);
                if (null != companyCode) {
                    LambdaQueryWrapper<CompanyDo> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(CompanyDo::getCompanyCode, companyCode.toString().split("\\.")[0]);
                    CompanyDo companyDo = companyDao.selectOne(wrapper);
                    if (null == companyDo) {
                        throw new BizException(SysConstant.Company_NotExist_Code, companyCode.toString().split("\\.")[0]);
                    }
                    companyID = companyDo.getId();
                }
                flag1 = false;
            }
            add(addReq, userId, companyID);
        }
        return null;
    }

    @Override
    public void exportExcel(HttpServletResponse response) throws IOException {
        LambdaQueryWrapper<ProductInfoDo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductInfoDo::getType, 2);
        List<ProductInfoDo> productInfoDoList = dao.selectList(wrapper);
        List<FbaProductExportVo> exportList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(productInfoDoList)) {
            productInfoDoList.forEach(productInfoDo -> {
                FbaProductExportVo fbaProductExportVo = new FbaProductExportVo();
                BeanUtils.copyProperties(productInfoDo, fbaProductExportVo);
//                DicBusinessItemDo businessItemDo = dicBusinessItemDao.selectById(productInfoDo.getProductType());
//                if(businessItemDo != null){
//                    fbaProductExportVo.setProductType(businessItemDo.getDicItemValue());
//                }
                exportList.add(fbaProductExportVo);
            });
        }
        ExcelUtils.exportExcel(exportList, FbaProductExportVo.class, "fba产品导出单", new ExportParams(), response);

    }

    @Override
    public String exportProductCodePdf(Long id, int count, HttpServletResponse response) {
        return null;
    }

    @Override
    public List<String> getTitles(MultipartFile file) throws Exception {
        if (StringUtils.isEmpty(file.getName())) {
            throw new BizException(SysConstant.File_Name_Null);
        }
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!GlobalConstants.IMG_TYPE_XLS.equals(suffix.toUpperCase()) &&
                !GlobalConstants.IMG_TYPE_XLSX.equals(suffix.toUpperCase())) {
            throw new BizException(SysConstant.File_Form_Incorrect);
        }
        List<String> list = ImportExcelUtil.getExcelTitle(file.getInputStream(), file.getOriginalFilename());
        if (list.size() == 0) {
            throw new BizException(SysConstant.No_Data);
        }
        return list;
    }

    private static Boolean isNumber(String s) throws UnsupportedEncodingException {
        Pattern pattern1 = Pattern.compile("^[A-Za-z]+$");//整数
        Pattern pattern2 = Pattern.compile("^[+-]?0\\.\\d+?$");//小于1的整数
        Pattern pattern3 = Pattern.compile("^[+-]?\\d+(\\.\\d+)?$");//任意浮点
        boolean matches1 = pattern1.matcher(s).matches();
        boolean matches2 = pattern2.matcher(s).matches();
        boolean matches3 = pattern3.matcher(s).matches();
        if (matches1 || matches2 || matches3) {
            return true;
        }
        return false;
    }
}
